using System;
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;

public class WeaponHands : MonoBehaviour
{
	public const float maxDeltaTime = 0.04f;

	public static int numCreatedBullets;

	public static bool shells = true;

	[Tooltip("Идентификатор оружия")]
	public string ID = "ak12";

	[HideInInspector]
	public float recoil;

	[Tooltip("Скорость увеличения отдачи")]
	public int recoilSteps;

	[Tooltip("Максимальный угол отдачи, в градусах")]
	[Range(0f, 10f)]
	public float recoilMax;

	[Tooltip("Скорость уменьшения отдачи, в градусы/секунду")]
	[Range(0f, 180f)]
	public float recoilDecrease;

	[Tooltip("Угол отклонения после выстрела")]
	[Range(0f, 10f)]
	public float shotDirection;

	private float randomShotAngle;

	[Space(6f)]
	[Tooltip("Позиция и угол ствола")]
	public Vector3 bolt = default(Vector3);

	[Space(6f)]
	[Tooltip("Автоматическое оружие")]
	public bool automat;

	[Tooltip("Скорострельность. Кол-во выстрелов в минуту")]
	public int shotsInMinute = 750;

	[Tooltip("Кол-во патронов в одном магазине,\n0 - бесконечно")]
	public int magazineMax = 30;

	[Tooltip("Множитель угола для разброса пуль, если ствол оружия длинный, то разброс должен быть меньше")]
	[Range(0f, 2f)]
	public float scaleAngleScatter = 1f;

	[Tooltip("Задержка перед запуском пули после нажатия на курок, в скндх.")]
	public float delayBullet;

	public WeaponCartridge cartridge;

	[Space(8f)]
	public AudioClip audioShot;

	[Tooltip("Случайная анимация выстрела")]
	public NameAnimationFire[] shotAnimations = new NameAnimationFire[0];

	public KeyframeAnimationName keyframe = default(KeyframeAnimationName);

	[Space(8f)]
	[Tooltip("Добавление патронов в магазин после анимации перезарядки")]
	public int addBulletsReload = 1;

	[Tooltip("Число выстрелов для анимации")]
	public int stepAnimationShot;

	[Tooltip("Дополнительная задержка/заморозка оружия после выстрела")]
	public float timeFreezeShot;

	public SoundFrameAnimation[] soundsAnimation = new SoundFrameAnimation[0];

	public SourceWeaponShell shell = new SourceWeaponShell(0);

	public SourceWeaponShell magazineAnimation = new SourceWeaponShell(0);

	public SpriteRenderer renderInSpare;

	[Tooltip("Линия для лазера (необязательно)")]
	public LineRenderer laser;

	[HideInInspector]
	private float distLaser = 123f;

	[HideInInspector]
	public bool stateReload;

	[HideInInspector]
	public AudioSource audioSource;

	[HideInInspector]
	public AnimatorCurve animator;

	private float timePauseShot;

	private float pauseShot;

	private bool laserLastValue = true;

	private float recoilSpeed;

	private bool currentTriggerShot = true;

	private bool abortAddBullets;

	private int lastFrameID = -1;

	private int numShots;

	private float timeMarkAnimationShot;

	private int magazCurrent = 1000000;

	private Vector2 globalPosition = default(Vector2);

	private float angleRad;

	private RaycastHit2D hitLaser;

	private Collider2D bulletHitCollider;

	private Vector3 localPoint;

	private Vector2 rayDirection;

	private bool emptyMagazine;

	private string nameAnimationBolt;

	private bool runShell;

	private bool runMagazin;

	private int b;

	private int idAnimationShot;

	public int magazine
	{
		get
		{
			magazCurrent = Mathf.Min(magazineMax, magazCurrent);
			if (magazineMax == 0)
			{
				magazCurrent = 1;
			}
			return magazCurrent;
		}
		set
		{
			magazineMax = Mathf.Max(0, magazineMax);
			magazCurrent = Mathf.Min(value, magazineMax);
			if (magazineMax == 0)
			{
				magazCurrent = 1;
			}
		}
	}

	private void Awake()
	{
		audioSource = base.gameObject.GetComponentInParent<AudioSource>();
		timePauseShot = 60f / (float)shotsInMinute * Time.timeScale;
		timePauseShot = Mathf.Round(timePauseShot * 100000f) / 100000f;
		recoilSteps = Mathf.Max(1, recoilSteps);
		recoilSpeed = recoilMax / (float)recoilSteps + timePauseShot * recoilDecrease;
		recoilSpeed = Mathf.Floor(recoilSpeed * 10000f) / 10000f;
		shell.Awake(base.gameObject.name);
		magazineAnimation.Awake(base.gameObject.name);
		cartridge.AwakeWeapon(this);
		SetActiveLaser(active: false);
	}

	private void OnDrawGizmos()
	{
		if (base.enabled)
		{
			if (cartridge != null)
			{
				cartridge.OnDrawGizmosWeapon(this);
			}
			if (shell.angle != shell.angleScatter)
			{
				Gizmos.color = new Color(1f, 0.7f, 0f);
				globalPosition = base.transform.TransformPoint(shell.position.x, shell.position.y, 0f);
				Vector3 eulerAngles = base.transform.rotation.eulerAngles;
				angleRad = (eulerAngles.z + (float)shell.angle) * ((float)Math.PI / 180f);
				Gizmos.DrawLine(globalPosition, new Vector2(globalPosition.x + Mathf.Cos(angleRad) * 1f, globalPosition.y + Mathf.Sin(angleRad) * 1f));
				angleRad += (float)shell.angleScatter * ((float)Math.PI / 180f);
				Gizmos.DrawLine(globalPosition, new Vector2(globalPosition.x + Mathf.Cos(angleRad) * 1f, globalPosition.y + Mathf.Sin(angleRad) * 1f));
				Vector3 eulerAngles2 = base.transform.rotation.eulerAngles;
				angleRad = (eulerAngles2.z + (float)shell.angleRotation) * ((float)Math.PI / 180f);
				Gizmos.DrawLine(globalPosition, new Vector2(globalPosition.x + Mathf.Cos(angleRad) * 0.25f, globalPosition.y + Mathf.Sin(angleRad) * 0.25f));
			}
			if (magazineAnimation.angle != magazineAnimation.angleScatter)
			{
				Gizmos.color = new Color(1f, 1f, 1f);
				globalPosition = base.transform.TransformPoint(magazineAnimation.position.x, magazineAnimation.position.y, 0f);
				Vector3 eulerAngles3 = base.transform.rotation.eulerAngles;
				angleRad = (eulerAngles3.z + (float)magazineAnimation.angle) * ((float)Math.PI / 180f);
				Gizmos.DrawLine(globalPosition, new Vector2(globalPosition.x + Mathf.Cos(angleRad) * 1f, globalPosition.y + Mathf.Sin(angleRad) * 1f));
				angleRad += (float)magazineAnimation.angleScatter * ((float)Math.PI / 180f);
				Gizmos.DrawLine(globalPosition, new Vector2(globalPosition.x + Mathf.Cos(angleRad) * 1f, globalPosition.y + Mathf.Sin(angleRad) * 1f));
				Vector3 eulerAngles4 = base.transform.rotation.eulerAngles;
				angleRad = (eulerAngles4.z + (float)magazineAnimation.angleRotation) * ((float)Math.PI / 180f);
				Gizmos.DrawLine(globalPosition, new Vector2(globalPosition.x + Mathf.Cos(angleRad) * 0.25f, globalPosition.y + Mathf.Sin(angleRad) * 0.25f));
			}
		}
	}

	private void OnDrawGizmosSelected()
	{
		if (base.enabled && cartridge != null)
		{
			cartridge.OnDrawGizmosSelectedWeapon(this);
		}
	}

	private void Start()
	{
		cartridge.StartWeapon(this);
		stepAnimationShot = Mathf.Max(1, stepAnimationShot);
	}

	private void OnEnable()
	{
		distLaser = Camera.main.aspect * Camera.main.orthographicSize * 2f;
	}

	private void OnDisable()
	{
		SetActiveLaser(active: false);
	}

	public void OnSwitchWeapon(bool value, bool enableSpareRender)
	{
		base.gameObject.SetActive(value);
		SetActiveRenderSpare(enableSpareRender);
		animator = GetComponent<AnimatorCurve>();
		animator.SetRenderActive(value);
		if (value)
		{
			if (stateReload)
			{
				animator.Play();
			}
			else if (magazine == 0)
			{
				StartReload();
			}
			else if (!stateReload && !string.IsNullOrEmpty(keyframe.onEnable))
			{
				animator.SwitchAnimation(keyframe.onEnable);
				animator.GotoAndPlay(0);
			}
			else if (!stateReload && shotAnimations.Length != 0 && animator.clip.HasKeyframe(shotAnimations[0].animation))
			{
				animator.SwitchAnimation(shotAnimations[0].animation);
				animator.GotoAndStop(0);
			}
			else
			{
				animator.ResetAnimationRange(0);
				animator.GotoAndStop(0);
			}
		}
		else
		{
			animator.Stop();
		}
	}

	private void FixedUpdate()
	{
		if (!(laser != null) || stateReload || animator.isPlaying)
		{
			return;
		}
		SetActiveLaser(active: true);
		rayDirection = base.transform.right;
		ref Vector2 reference = ref rayDirection;
		float x = rayDirection.x;
		Vector3 lossyScale = base.transform.lossyScale;
		reference.x = x * lossyScale.x;
		ref Vector2 reference2 = ref rayDirection;
		float y = rayDirection.y;
		Vector3 lossyScale2 = base.transform.lossyScale;
		reference2.y = y * lossyScale2.x;
		laser.SetPosition(1, new Vector3(distLaser, bolt.y));
		if (!(bulletHitCollider == null))
		{
			bulletHitCollider.enabled = true;
			hitLaser = Physics2D.Raycast(GetPositionBolt(), rayDirection, distLaser, cartridge.sourceBullets.layerBodies.value);
			if (hitLaser.collider != null)
			{
				localPoint = base.transform.InverseTransformPoint(hitLaser.point);
				localPoint.y = bolt.y;
				laser.SetPosition(1, localPoint);
			}
		}
	}

	private void LateUpdate()
	{
		if (animator.isPlaying && lastFrameID != animator.frameTimeline)
		{
			lastFrameID = animator.frameTimeline;
			for (b = 0; b < soundsAnimation.Length; b++)
			{
				if (soundsAnimation[b].frameID == lastFrameID && audioSource != null)
				{
					audioSource.PlayOneShot(soundsAnimation[b].sound);
					break;
				}
			}
		}
		if (stateReload && animator.currentFrame == animator.totalFrames)
		{
			if (animator.currentAnimation == keyframe.addBullet || animator.currentAnimation == keyframe.anotherBullet)
			{
				AddBullets(addBulletsReload);
				if (magazine < magazineMax && !abortAddBullets)
				{
					animator.SwitchAnimation(keyframe.anotherBullet);
					animator.GotoAndPlay(0);
				}
				else if (emptyMagazine)
				{
					animator.SwitchAnimation(keyframe.bolt);
					animator.GotoAndPlay(0);
				}
				else
				{
					animator.SwitchAnimation(keyframe.completeBullet);
					animator.GotoAndPlay(0);
				}
			}
			else if (animator.currentAnimation == keyframe.bolt || animator.currentAnimation == keyframe.completeBullet)
			{
				StopReload();
			}
			else if (shotAnimations.Length != 0 && animator.clip.HasKeyframe(shotAnimations[0].animation))
			{
				animator.SwitchAnimation(shotAnimations[0].animation);
				animator.GotoAndStop(0);
				AddBullets(addBulletsReload);
				StopReload();
			}
			else
			{
				AddBullets(addBulletsReload);
				StopReload();
			}
		}
		if (runShell && shell.frame == animator.frameTimeline)
		{
			shell.Reset(base.transform);
			runShell = false;
		}
		if (stateReload && runMagazin && magazineAnimation.frame == animator.frameTimeline)
		{
			magazineAnimation.Reset(base.transform);
			runMagazin = false;
		}
	}

	public bool IsReady(bool trigger)
	{
		if (pauseShot < 0f)
		{
			pauseShot += Time.deltaTime;
		}
		if (Time.time < timeMarkAnimationShot || stateReload)
		{
			return false;
		}
		if (trigger == currentTriggerShot)
		{
			currentTriggerShot = true;
		}
		else
		{
			trigger = false;
		}
		trigger = (trigger && base.enabled && pauseShot >= 0f && magazine > 0);
		return trigger && currentTriggerShot;
	}

	public void OnKeyShot()
	{
		if (!abortAddBullets && stateReload && !string.IsNullOrEmpty(animator.currentAnimation) && animator.currentAnimation == keyframe.anotherBullet && magazine > 0)
		{
			abortAddBullets = true;
			if (!string.IsNullOrEmpty(keyframe.bolt) && emptyMagazine)
			{
				animator.SwitchAnimation(keyframe.bolt);
				animator.GotoAndPlay(0);
			}
			else if (!string.IsNullOrEmpty(keyframe.completeBullet))
			{
				animator.SwitchAnimation(keyframe.completeBullet);
				animator.GotoAndPlay(0);
			}
		}
		if (magazine <= 0)
		{
			StartReload();
		}
	}

	public void Shot(float distToAim)
	{
		if (audioSource != null)
		{
            Debug.Log("射击声音");
			audioSource.clip = audioShot;
            audioSource.Play();
            //audioSource.PlayOneShot(audioShot);
            //var obj = new GameObject();
            //var audio = obj.AddComponent<AudioSource>();
            //audio.clip = audioShot;
            //obj.AddComponent<AudioCallback>().init();
		}
		pauseShot = 0f - timePauseShot;
		recoil = Mathf.Min(recoil + recoilSpeed, recoilMax + randomShotAngle);
		randomShotAngle = 0f - shotDirection + Mathf.Ceil(UnityEngine.Random.value * shotDirection * 200f) / 100f;
		runShell = (shells && shell.frame != 0);
		if (shells && shell.frame == 0)
		{
			shell.Reset(base.transform);
		}
		if (magazineMax > 0)
		{
			magazine--;
		}
		currentTriggerShot = automat;
		if (magazineMax == 1 && !stateReload)
		{
			StartReload();
		}
		else
		{
			AnimationShot();
		}
		if (delayBullet == 0f)
		{
			cartridge.Shot(this, distToAim);
		}
		else
		{
			StartCoroutine(ShotDelay(distToAim));
		}
	}

	public IEnumerator ShotDelay(float distToAim)
	{
		yield return new WaitForSeconds(delayBullet);
		cartridge.Shot(this, distToAim);
	}

	public void OnHitBullet(HitBullet hitBullet)
	{
		if (hitBullet.countHits == 1)
		{
			bulletHitCollider = hitBullet.collider;
		}
	}

	private void AnimationShot()
	{
		if (shotAnimations.Length == 0)
		{
			animator.GotoAndPlay(1);
			return;
		}
		numShots++;
		if (shotAnimations.Length == 1)
		{
			idAnimationShot = 0;
		}
		else if (shotAnimations.Length == 2)
		{
			idAnimationShot++;
			idAnimationShot %= 2;
		}
		else if (shotAnimations.Length >= 3)
		{
			idAnimationShot = UnityEngine.Random.Range(0, shotAnimations.Length);
		}
		if (shotAnimations[idAnimationShot].fire != null)
		{
			shotAnimations[idAnimationShot].fire.OnShot();
		}
		if (numShots % stepAnimationShot == 0 && animator.clip.HasKeyframe(shotAnimations[idAnimationShot].animation))
		{
			animator.SwitchAnimation(shotAnimations[idAnimationShot].animation);
			animator.GotoAndPlay(0);
			timeMarkAnimationShot = Time.time + timeFreezeShot;
			if (animator.lastFrameClip - animator.startFrameClip >= 6)
			{
				SetActiveLaser(active: false);
			}
		}
		else
		{
			animator.ResetAnimationRange(0);
			animator.Stop();
		}
	}

	public bool StartReload()
	{
		if (base.enabled && !stateReload && magazineMax > 0 && magazine < magazineMax)
		{
			if (!string.IsNullOrEmpty(keyframe.addBullet))
			{
				animator.SwitchAnimation(keyframe.addBullet);
				animator.GotoAndPlay(0);
			}
			else if (animator.clip.HasKeyframe("reload"))
			{
				animator.SwitchAnimation("reload");
				animator.GotoAndPlay(0);
			}
			else
			{
				animator.GotoAndPlay(1);
			}
			SetActiveLaser(active: false);
			emptyMagazine = (magazine == 0);
			stateReload = true;
			runMagazin = (shells && magazineAnimation.frame != 0);
			if (string.IsNullOrEmpty(keyframe.anotherBullet))
			{
				numShots = 0;
			}
			return true;
		}
		return false;
	}

	public void AddBullets(int bullets)
	{
		bullets = Mathf.Min(bullets, magazineMax);
		magazine += bullets;
	}

	public void StopReload()
	{
		if (!stateReload)
		{
			base.transform.localRotation = default(Quaternion);
		}
		animator.Stop();
		stateReload = false;
		abortAddBullets = false;
		base.enabled = true;
		SetActiveLaser(active: true);
	}

	public float GetRecoil(float deltaTime)
	{
		deltaTime = Mathf.Min(0.04f, deltaTime);
		recoil = Mathf.Max(recoil - recoilDecrease * deltaTime, 0f);
		return recoil;
	}

	public Vector3 GetPositionBolt()
	{
		return base.transform.TransformPoint(bolt.x, bolt.y, 0f);
	}

	public float GetAngleBolt()
	{
		float z = bolt.z;
		Vector3 eulerAngles = base.transform.rotation.eulerAngles;
		return z + eulerAngles.z;
	}

	public void SetActiveLaser(bool active)
	{
		if (laser == null)
		{
			laserLastValue = false;
		}
		else if (active != laser.enabled)
		{
			laserLastValue = laser.enabled;
			laser.enabled = active;
		}
	}

	public void SetActiveLaser()
	{
		SetActiveLaser(laserLastValue);
	}

	public void SetActiveRenderSpare(bool value)
	{
		if (renderInSpare != null)
		{
			renderInSpare.gameObject.SetActive(value);
		}
	}

	public void DestroyWeapon()
	{
		if (renderInSpare != null)
		{
			UnityEngine.Object.Destroy(renderInSpare.gameObject);
		}
		UnityEngine.Debug.Log("DestroyWeapon");
		UnityEngine.Object.Destroy(base.gameObject);
	}
}
